#!/usr/bin/env python3.11
# -*- encoding: utf-8 -*-
"""
@File    :   schema.py
@Time    :   2024/05/28 09:16:53
@Author  :   windstarry 
@Version :   1.0
"""
# here put the import lib
from datetime import datetime
from typing import List, Optional, Type, Any
from django.contrib.auth import get_user_model
from django.contrib.auth.models import AbstractUser
from django.db import transaction

from ninja import Field
from ninja_schema import Schema, ModelSchema, model_validator
from ninja_extra import service_resolver, status
from ninja_extra.controllers import RouteContext
from ninja_extra.exceptions import APIException
from core.schemas import CoreModelSchema
from .models import Role


# 获取用户模型
UserModel = get_user_model()


# 用户登录请求字段
class LoginSchema(Schema):
    username: str = Field(..., description="用户名")
    password: str = Field(..., description="密码")


class UserInfoSchema(ModelSchema):
    class Config:
        model = UserModel
        include = ("id", "username", "nickname", "status")


class UserInSchema(CoreModelSchema):
    roles: list[int]

    class Config:
        model = UserModel
        include = [
            "username",
            "password",
            "status",
        ]

    @model_validator("roles", mode="before")
    def roles_validate(cls, value_data):
        # 验证角色id是否存在
        for rid in value_data:
            if not Role.objects.filter(id=rid).exists():
                raise APIException("角色不存在")
        return value_data

    @model_validator("username")
    def unique_username(cls, value_data):
        if UserModel.objects.filter(username__icontains=value_data).exists():
            raise APIException("用户名已存在")
        return value_data

    @transaction.atomic
    def create(self, **kwargs: Any) -> Type[AbstractUser]:
        """
        创建一个新的用户实例。

        参数:
        self -- 实例本身。
        **kwargs -- 创建用户时额外传递的关键字参数。

        返回值:
        返回创建的用户模型的实例。

        """
        # 获取当前的路由上下文，并从中解析出请求用户
        context: RouteContext = service_resolver(RouteContext)
        # 创建一个字典，排除None值
        _data = self.dict(exclude_none=True)
        # 设置创建者和修改者为当前请求的用户
        _data["creator"] = context.request.user
        _data["modifier"] = context.request.user
        # 更新字典数据，加入额外的kwargs参数
        _data.update(kwargs)
        # 使用提供的数据创建用户实例并返回
        return UserModel.objects.create_user(**_data)

class RoleActive(Schema):
    rid: int = Field(description="角色id")
    status: int = Field(default=1, description="激活角色 5 正常 1 删除 9")


class UserUpdateSchema(CoreModelSchema):
    roles: List[RoleActive] = Field(..., description="选择角色列表")

    class Config:
        model = UserModel
        include = [
            "nickname",
            "password",
        ]

    @model_validator("roles", mode="before")
    def roles_validate(cls, value_data):
        rids = [role.get("rid") for role in value_data]
        # 验证角色id是否存在
        for rid in rids:
            if not Role.objects.filter(id=rid).exists():
                raise APIException("角色不存在")
        return value_data


class RoleSchema(ModelSchema):
    class Config:
        model = Role
        include = ("id", "name", "desc")


class UserRoleSchema(Schema):
    user: UserInfoSchema = Field(..., description="用户信息")
    roles: List[int] = Field(..., description="用户拥有角色id信息")


class RoleInSchema(CoreModelSchema):
    menus: List[int] = Field(..., description="角色拥有菜单id信息")

    class Config:
        model = Role
        include = [
            "name",
            "desc",
        ]

    @model_validator("name")
    def unique_name(cls, value_data):
        context: RouteContext = service_resolver(RouteContext)
        if context.kwargs.get("rid"):
            if (
                not Role.objects.filter(name__contains=value_data)
                .exclude(id=context.kwargs.get("rid"))
                .exists()
            ):
                return value_data
        elif not Role.objects.filter(name__contains=value_data).exists():
            return value_data
        raise APIException("角色名已存在")

    @transaction.atomic
    def create(self, **kwargs: Any):
        # 获取当前的路由上下文，并从中解析出请求用户
        context: RouteContext = service_resolver(RouteContext)
        _data = self.dict(exclude_none=True)
        # 设置创建者和修改者为当前请求的用户
        _data["creator"] = context.request.user
        _data["modifier"] = context.request.user
        # 更新字典数据，加入额外的kwargs参数
        _data.update(kwargs)
        return Role.objects.create(**_data)


class UserTokenOutSchema(Schema):
    token: str
    user: UserInfoSchema
    token_exp_date: Optional[datetime]
